#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QThread>
#include <QStandardPaths>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QDir *dataDir = new QDir;
//    m_dirStandard = QStandardPaths::standardLocations(QStandardPaths::DataLocation).at(0);
    m_dirStandard = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).at(0) +
             "/" + qApp->applicationName();
    if(!dataDir->exists(m_dirStandard)) {
        dataDir->mkdir(m_dirStandard);
    }
    m_fileHistory = m_dirStandard + "/history";
    qDebug() << "m_dirStandard" << m_dirStandard;

    ui->textEdit->setFontFamily("Consolas");
    textEditLoadText(m_fileWelcome);

    groupCheckbox = new QButtonGroup(this);
    groupCheckbox->addButton(ui->checkBox_A, 1);
    groupCheckbox->addButton(ui->checkBox_B, 2);
    groupCheckbox->addButton(ui->checkBox_C, 3);

    connect(this, &MainWindow::signal_messageBox, this, &MainWindow::slot_messageBox);

    m_listA = new QList<ItemDesc>;
    m_listB = new QList<ItemDesc>;
    m_listC = new QList<ItemDesc>;

    QString strFileToLoad;
    QFile file(m_fileHistory);
    bool ret = file.open(QIODevice::ReadOnly | QIODevice::Text);
    if(!ret)
    {
      qDebug() << "open hsitory failed";
      strFileToLoad = m_fileDefaultConf;
    }
    else
    {
       QByteArray byteArray = file.readAll();
       char *str = byteArray.data();
       strFileToLoad = QString::fromUtf8(str);
       file.close();
    }
    ItemParseVal parseRet = getTestItemsFromFile(strFileToLoad);
    if(parseRet != E_PARSE_OK) {
        //emit(signal_messageBox(1, "文件解析错误"));
        ui->textEdit->append("*** 配置文件解析错误: " + QString::number((int)parseRet));
    }

    // A
    m_modelA = new QStandardItemModel();
    m_delegateA = new ItemDelegate(this);
    m_proxyModelA = new QSortFilterProxyModel(ui->listView_A);
    initListView(m_totalItemsA, m_listA, m_modelA, m_proxyModelA, m_delegateA, ui->listView_A);
    // B
    m_modelB = new QStandardItemModel();
    m_delegateB = new ItemDelegate(this);
    m_proxyModelB = new QSortFilterProxyModel(ui->listView_B);
    initListView(m_totalItemsB, m_listB, m_modelB, m_proxyModelB, m_delegateB, ui->listView_B);
    // C
    m_modelC = new QStandardItemModel();
    m_delegateC = new ItemDelegate(this);
    m_proxyModelC = new QSortFilterProxyModel(ui->listView_C);
    initListView(m_totalItemsC, m_listC, m_modelC, m_proxyModelC, m_delegateC, ui->listView_C);

//    ui->checkBox_A->setCheckState(Qt::Unchecked);
//    ui->checkBox_A->setCheckState(Qt::Checked);

    // thread_1
    m_thread = new ThreadHandle();
    connect(m_thread, &ThreadHandle::signal_testReturn, this, &MainWindow::slot_testProc);
    connect(m_thread, &ThreadHandle::signal_testCmdSync, this, &MainWindow::slot_testCmdSync);
    connect(m_thread, &ThreadHandle::signal_adbSyncEnd, this, &MainWindow::slot_adbSyncEnd);

    // thread_2
    m_thread2 = new ThreadHandle();
    connect(m_thread2, &ThreadHandle::signal_testReturn, this, &MainWindow::slot_testProc);
//    connect(m_thread2, &ThreadHandle::signal_testCmdSync, this, &MainWindow::slot_testCmdSync);

    // thread detection
    m_trdDetect = new ThreadDetect();
    connect(m_trdDetect, &ThreadDetect::signal_adbDetect, this, &MainWindow::slot_adbDetect);
    m_trdDetect->start();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::slot_messageBox(int type, QString message)
{
    if(type == 1) {
        QMessageBox::warning(this, "", message);
    } else {
        QMessageBox::information(this, "", message);
    }
}

void MainWindow::textEditLoadText(QString fileName)
{
    QFile file(fileName);
    bool bRet = file.open(QIODevice::ReadOnly | QIODevice::Text);
    if(!bRet) {
       return;
    }
    QByteArray byteArray = file.readAll();
    char *str = byteArray.data();
    QString strWelcome = QString::fromUtf8(str);
    ui->textEdit->append(strWelcome);
}

ItemParseVal MainWindow::getTestItemsFromFile(QString fileName)
{
    QFile file(fileName);
    bool bRet = file.open(QIODevice::ReadOnly | QIODevice::Text);
    if(!bRet) {
       return E_PARSE_ERROR_FILE;
    }

    QByteArray byteArray = file.readAll();
    char *jsonStr = byteArray.data();

    cJSON *root = cJSON_Parse(jsonStr);
    if(!root) {
        return E_PARSE_ERROR_ROOT;
    }

    cJSON *i_str;
    cJSON *i_total;
    int totalJson = 0;

    i_str = cJSON_GetObjectItem(root, "strTestHault");
    if(i_str) {
        m_strTestHault = QString::fromUtf8(cJSON_GetStringValue(i_str));
    }
    i_str = cJSON_GetObjectItem(root, "strTesting");
    if(i_str) {
        m_strTesting = QString::fromUtf8(cJSON_GetStringValue(i_str));
    }
    i_str = cJSON_GetObjectItem(root, "strTestOK");
    if(i_str) {
        m_strTestOK = QString::fromUtf8(cJSON_GetStringValue(i_str));
    }
    i_str = cJSON_GetObjectItem(root, "strTestNG");
    if(i_str) {
        m_strTestNG = QString::fromUtf8(cJSON_GetStringValue(i_str));
    }
    i_str = cJSON_GetObjectItem(root, "strWaitJudge");
    if(i_str) {
        m_strWaitJudge = QString::fromUtf8(cJSON_GetStringValue(i_str));
    }

    i_str = cJSON_GetObjectItem(root, "cmdEnterTest");
    if(i_str) {
        m_cmdEnterTestMode = QString::fromUtf8(cJSON_GetStringValue(i_str));
    }

    i_str = cJSON_GetObjectItem(root, "cmdExitTest");
    if(i_str) {
        m_cmdExitTestMode = QString::fromUtf8(cJSON_GetStringValue(i_str));
    }

    i_total = cJSON_GetObjectItem(root, "totalItems");
    if(i_total)
        totalJson = cJSON_GetNumberValue(i_total);

    QFileInfo fileInfo(fileName);
    QString userPath = fileInfo.absolutePath();

    for(int i = 1; i <= totalJson; i++)
    {
        ItemDesc itemDesc;
        char tmp_str[64];
        snprintf(tmp_str, 64, "%d", i);
        cJSON *item = cJSON_GetObjectItem(root, tmp_str);
        cJSON *i_node;

        i_node = cJSON_GetObjectItem(item, "name");
        if(i_node)
            itemDesc.name = QString::fromUtf8(cJSON_GetStringValue(i_node));
        else
            goto error_data;

        i_node = cJSON_GetObjectItem(item, "command");
        if(i_node)
            itemDesc.command = QString::fromUtf8(cJSON_GetStringValue(i_node));
        else
            goto error_data;

        i_node = cJSON_GetObjectItem(item, "exit_cmd");
        if(i_node) {
            QString tmp = QString::fromUtf8(cJSON_GetStringValue(i_node));
            if(tmp.compare("null"))
                itemDesc.exitCmd = tmp;
        }

        i_node = cJSON_GetObjectItem(item, "info");
        if(i_node) {
            QString tmp = QString::fromUtf8(cJSON_GetStringValue(i_node));
            if(tmp.compare("null"))
                itemDesc.info = userPath + "/" + tmp;
        }

        i_node = cJSON_GetObjectItem(item, "type");
        if(i_node)
            itemDesc.type = QString::fromUtf8(cJSON_GetStringValue(i_node));
        else
            goto error_data;

        if(QString::compare(itemDesc.type, "auto") == 0) {
            m_listA->append(itemDesc);
            ++m_totalItemsA;
        } else if(QString::compare(itemDesc.type, "half-auto") == 0) {
            m_listB->append(itemDesc);
            ++m_totalItemsB;
        } else if(QString::compare(itemDesc.type, "manual") == 0) {
            m_listC->append(itemDesc);
            ++m_totalItemsC;
        }
    }
//    qDebug() << "m_totalItemsA" << m_totalItemsA;
//    qDebug() << "m_totalItemsB" << m_totalItemsB;
//    qDebug() << "m_totalItemsC" << m_totalItemsC;
    file.close();
    return E_PARSE_OK;
error_data:
    file.close();
    return E_PARSE_ERROR_DATA;
}

void MainWindow::initListView(int totalItems, QList<ItemDesc> *list,
                              QStandardItemModel *model,
                              QSortFilterProxyModel *proxyModel,
                              ItemDelegate *delegate,
                              QListView *listView)
{
    if(totalItems == 0)
        return;
    int total = totalItems;
    for (int i = 0; i < total; ++i)
    {
        QStandardItem *item = new QStandardItem();

        ItemData itemData;
        itemData.name = list->at(i).name;
        itemData.data = m_strTestHault;
        ItemStatus itemStatus = S_BLUE;

        item->setData(itemStatus, Qt::UserRole);
        item->setData(QVariant::fromValue(itemData), Qt::UserRole+1);

        model->appendRow(item);
    }

    proxyModel->setSourceModel(model);
    proxyModel->setFilterRole(Qt::UserRole);
    proxyModel->setDynamicSortFilter(true);
    listView->setItemDelegate(delegate);
    listView->setModel(proxyModel);
    listView->setViewMode(QListView::IconMode);
    listView->setDragEnabled(false);
    listView->setSpacing(15);

    QModelIndex index = proxyModel->index(0, 0);
    listView->setCurrentIndex(index);
}

void MainWindow::setItemStatus(QModelIndex &index, TestStatus testStat,
                               QStandardItemModel *model,
                               QSortFilterProxyModel *proxyModel)
{
    QModelIndex stdIdx = proxyModel->mapToSource(index);
    QVariant variant = stdIdx.data(Qt::UserRole+1);
    ItemData itemData = variant.value<ItemData>();
    ItemStatus status;
    QString strItem;
    switch(testStat)
    {
    case E_TEST_NO_BEGIN:
        strItem = m_strTestHault;
        status = S_BLUE;
        break;
    case E_TEST_PROC:
        strItem = m_strTesting;
        status = S_YELLOW;
        break;
    case E_TEST_RES_SUCCESS:
        strItem = m_strTestOK;
        status = S_GREEN;
        break;
    case E_TEST_RES_FAIL:
        strItem = m_strTestNG;
        status = S_RED;
        break;
    case E_TEST_WAIT_JUDGE:
        strItem = m_strWaitJudge;
        status = S_GRAY;
        break;
    default:
        strItem = m_strTestHault;
        status = S_BLUE;
        break;
    }
    itemData.data = strItem;
    model->setData(stdIdx, QVariant::fromValue(itemData), Qt::UserRole+1);
    model->setData(stdIdx, status, Qt::UserRole);
}

void MainWindow:: resetAllItems(QListView *listView,
                               QStandardItemModel *model,
                               QSortFilterProxyModel *proxyModel)
{
    QModelIndex index;
    int total = listView->model()->rowCount();
    for(int i = 0; i < total; i ++)
    {
        index = proxyModel->index(i, 0);
        setItemStatus(index, E_TEST_NO_BEGIN, model, proxyModel);
    }
    index = proxyModel->index(0, 0);
    listView->setCurrentIndex(index);
}

void MainWindow::switchTestingType(TestingType type)
{
    if(TT_NONE == type) {
        ui->checkBox_A->setEnabled(true);
        ui->checkBox_B->setEnabled(true);
        ui->checkBox_C->setEnabled(true);
        if(m_testingType == TT_AUTO)
            ui->listView_A->setEnabled(true);
        else if(m_testingType == TT_HALFAUTO)
            ui->listView_B->setEnabled(true);
        else if(m_testingType == TT_MANUAL)
            ui->listView_C->setEnabled(true);
    } else {
        ui->checkBox_A->setEnabled(false);
        ui->checkBox_B->setEnabled(false);
        ui->checkBox_C->setEnabled(false);
        if(type != TT_PREPARE && type != TT_EXIT)
        {
            ui->listView_A->setEnabled(false);
            ui->listView_B->setEnabled(false);
            ui->listView_C->setEnabled(false);
        }
    }
    m_testingType = type;
}

TestingType MainWindow::getTestingType()
{
    return m_testingType;
}

void MainWindow::slot_testProc(int devCnt)
{
    QModelIndex index;
    ThreadResult result = m_thread->getResult();

    switch(devCnt)
    {
    case 0:
        ui->labelADB->setText(m_strADBDisconnect);
        break;
    case 1:
        ui->labelADB->setText(m_strADBConnected);
        break;
    default:
        ui->labelADB->setText(m_strADBMultiple);
        break;
    }

    if(getTestingType() == TT_AUTO)
    {
        index = ui->listView_A->currentIndex();
        if(result == E_THREAD_RES_SUCCESS) {
           setItemStatus(index, E_TEST_RES_SUCCESS, m_modelA, m_proxyModelA);
        } else if(result == E_THREAD_RES_FAIL) {
           setItemStatus(index, E_TEST_RES_FAIL, m_modelA, m_proxyModelA);
        } else if(result == E_THREAD_ERR_MODE) {
            resetAllItems(ui->listView_A, m_modelA, m_proxyModelA);
            ui->Btn_Test_A->setEnabled(true);
            ui->Btn_Single_A->setEnabled(true);
            ui->Btn_Reset_A->setEnabled(true);
            emit(signal_messageBox(0, m_strErrorMode));
            switchTestingType(TT_NONE);
            return;
         } else {
            /* test is interruptted */
            resetAllItems(ui->listView_A, m_modelA, m_proxyModelA);
            ui->Btn_Test_A->setEnabled(true);
            ui->Btn_Single_A->setEnabled(true);
            ui->Btn_Reset_A->setEnabled(true);
            emit(signal_messageBox(1, m_strStartFailed));
            switchTestingType(TT_NONE);
            return;
        }
        /* 进行下一项测试 */
        if(m_bTestSingleA) {
            m_bTestSingleA = false;
            ui->Btn_Test_A->setEnabled(true);
            ui->Btn_Single_A->setEnabled(true);
            ui->Btn_Reset_A->setEnabled(true);
            switchTestingType(TT_NONE);
        } else {
            int next_item = index.row() + 1;

            if(next_item < m_totalItemsA) {
                index = m_proxyModelA->index(next_item, 0);
                ui->listView_A->setCurrentIndex(index);
                setItemStatus(index, E_TEST_PROC, m_modelA, m_proxyModelA);

                // load info
                QString fileName = m_listA->at(next_item).info;
                if(!fileName.isEmpty())
                    textEditLoadText(fileName);

                ui->textEdit->append("*** " + m_listA->at(next_item).name);
                m_thread->setCommand(m_listA->at(next_item).command);
                m_thread->start();
            } else {
                /* finish all testA */
                ui->Btn_Test_A->setEnabled(true);
                ui->Btn_Single_A->setEnabled(true);
                ui->Btn_Reset_A->setEnabled(true);
                switchTestingType(TT_NONE);
            }
        }
    }
    else if(getTestingType() == TT_HALFAUTO)
    {
        index = ui->listView_B->currentIndex();
        if(result == E_THREAD_RES_SUCCESS) {
           setItemStatus(index, E_TEST_RES_SUCCESS, m_modelB, m_proxyModelB);
        } else if(result == E_THREAD_RES_FAIL) {
           setItemStatus(index, E_TEST_RES_FAIL, m_modelB, m_proxyModelB);
        } else if(result == E_THREAD_ERR_MODE) {
            resetAllItems(ui->listView_B, m_modelB, m_proxyModelB);
            ui->Btn_Test_B->setEnabled(true);
            ui->Btn_Reset_B->setEnabled(true);
            emit(signal_messageBox(0, m_strErrorMode));
            switchTestingType(TT_NONE);
            return;
        } else {
            /* test is interruptted */
            resetAllItems(ui->listView_B, m_modelB, m_proxyModelB);
            ui->Btn_Test_B->setEnabled(true);
            ui->Btn_Reset_B->setEnabled(true);
            emit(signal_messageBox(1, m_strStartFailed));
            switchTestingType(TT_NONE);
            return;
        }

        /* set ListVIew_B to next item */
        int next_item = index.row() + 1;
        if(next_item >= m_totalItemsB)
        {
            next_item = 0;
        }
        index = m_proxyModelB->index(next_item, 0);
        ui->listView_B->setCurrentIndex(index);

        // load info
        QString fileName = m_listB->at(next_item).info;
        if(!fileName.isEmpty())
            textEditLoadText(fileName);

        ui->Btn_Test_B->setEnabled(true);
        ui->Btn_Reset_B->setEnabled(true);
        switchTestingType(TT_NONE);
    }
    else if(getTestingType() == TT_MANUAL)
    {
        if(devCnt != 1)
        {
            resetAllItems(ui->listView_C, m_modelC, m_proxyModelC);
            enableBttons_C(true);
            emit(signal_messageBox(1, m_strStartFailed));
            switchTestingType(TT_NONE);
//            return;
        }
    }
    else if(getTestingType() == TT_PREPARE)
    {
        QString str1;
        if(result == E_THREAD_RES_SUCCESS) {
            str1 = "进入测试模式：成功";
            ui->textEdit->append(str1);
            emit(signal_messageBox(0, str1));
        } else if(result == E_THREAD_RES_FAIL) {
            str1 = "进入测试模式：失败";
            ui->textEdit->append(str1);
            emit(signal_messageBox(1, str1));
        }
        switchTestingType(TT_NONE);
    }
    else if(getTestingType() == TT_EXIT)
    {
        QString str2;
        if(result == E_THREAD_RES_SUCCESS) {
            str2 = "退出测试模式：成功";
            ui->textEdit->append(str2);
            emit(signal_messageBox(0, str2));
        } else if(result == E_THREAD_RES_FAIL) {
            str2 = "退出测试模式：失败";
            ui->textEdit->append(str2);
            emit(signal_messageBox(1, str2));
        }
        switchTestingType(TT_NONE);
    }
}

void MainWindow::slot_testCmdSync(QString strSync)
{
    QModelIndex index;
    if(m_testingType == TT_MANUAL)
    {
        index = ui->listView_C->currentIndex();
        if(strSync.contains("[NA]", Qt::CaseSensitive))
        {
            setItemStatus(index, E_TEST_WAIT_JUDGE, m_modelC, m_proxyModelC);
            ui->Btn_OK_C->setEnabled(true);
            ui->Btn_NG_C->setEnabled(true);
            ui->Btn_Reset_C->setEnabled(true);
        }
        else if(strSync.contains("[NG]", Qt::CaseSensitive))
        {
            setItemStatus(index, E_TEST_RES_FAIL, m_modelC, m_proxyModelC);
            // move to next item
            int next_item = index.row() + 1;
            if(next_item < m_totalItemsC) {
                index = m_proxyModelC->index(next_item, 0);
                ui->listView_C->setCurrentIndex(index);
            } else {
                /* finish all testC */
                index = m_proxyModelC->index(0, 0);
                ui->listView_C->setCurrentIndex(index);
            }
            enableBttons_C(true);
            switchTestingType(TT_NONE);
        }
        else if(strSync.contains("[MODE]", Qt::CaseSensitive))
        {
            resetAllItems(ui->listView_C, m_modelC, m_proxyModelC);
            enableBttons_C(true);
            emit(signal_messageBox(0, m_strErrorMode));
            switchTestingType(TT_NONE);
        }
        ui->textEdit->append("> " + strSync);
    }
}

void MainWindow::slot_adbSyncEnd()
{
//    qDebug() << __FUNCTION__;
    ui->Btn_Test_C->setEnabled(true);
}

void MainWindow::slot_adbDetect(int devCount, bool needRefresh)
{
    if(needRefresh)
    {
        qDebug() << __FUNCTION__ << __LINE__;
        switch(devCount)
        {
        case 0:
            ui->labelADB->setText(m_strADBDisconnect);
            break;
        case 1:
            ui->labelADB->setText(m_strADBConnected);
            break;
        default:
            ui->labelADB->setText(m_strADBMultiple);
            break;
        }

        if(devCount != 1)
        {
            resetAllItems(ui->listView_A, m_modelA, m_proxyModelA);
            resetAllItems(ui->listView_B, m_modelB, m_proxyModelB);
            resetAllItems(ui->listView_C, m_modelC, m_proxyModelC);
            if(getTestingType() == TT_MANUAL)
            {
                enableBttons_C(true);
                switchTestingType(TT_NONE);
            }
            ui->checkBox_A->setCheckState(Qt::Unchecked);
            ui->checkBox_A->setCheckState(Qt::Checked);
        }
    }
}

void MainWindow::enableBttons_C(bool enable)
{
    ui->Btn_Test_C->setEnabled(enable);
    ui->Btn_OK_C->setEnabled(enable);
    ui->Btn_NG_C->setEnabled(enable);
    ui->Btn_Reset_C->setEnabled(enable);
}

/* -------------------------------------------- */

void MainWindow::on_Btn_Test_A_clicked()
{
    if(m_totalItemsA <= 0)
        return;
    resetAllItems(ui->listView_A, m_modelA, m_proxyModelA);
    QModelIndex index = m_proxyModelA->index(0, 0);
    ui->listView_A->setCurrentIndex(index);
    setItemStatus(index, E_TEST_PROC, m_modelA, m_proxyModelA);

    switchTestingType(TT_AUTO);
    ui->textEdit->append("*** " + m_listA->at(0).name);
    m_thread->setCommand(m_listA->at(0).command);
    m_thread->start();

    ui->Btn_Test_A->setEnabled(false);
    ui->Btn_Single_A->setEnabled(false);
    ui->Btn_Reset_A->setEnabled(false);
}

void MainWindow::on_Btn_Reset_A_clicked()
{
    if(m_totalItemsA <= 0)
        return;
    resetAllItems(ui->listView_A, m_modelA, m_proxyModelA);
}

void MainWindow::on_checkBox_A_stateChanged(int arg1)
{
    if(arg1) {
        ui->Btn_Test_A->setEnabled(true);
        ui->Btn_Single_A->setEnabled(true);
        ui->Btn_Reset_A->setEnabled(true);
        ui->listView_A->setEnabled(true);

        // load info
        if(m_totalItemsA > 0) {
            QModelIndex index = ui->listView_A->currentIndex();
            int i_testItem = index.row();
            QString fileName = m_listA->at(i_testItem).info;
            if(!fileName.isEmpty())
                textEditLoadText(fileName);
        }
    } else {
        ui->Btn_Test_A->setEnabled(false);
        ui->Btn_Single_A->setEnabled(false);
        ui->Btn_Reset_A->setEnabled(false);
        ui->listView_A->setEnabled(false);
    }
}

void MainWindow::on_checkBox_B_stateChanged(int arg1)
{
    if(arg1) {
        ui->Btn_Test_B->setEnabled(true);
        ui->Btn_Reset_B->setEnabled(true);
        ui->listView_B->setEnabled(true);

        // load info
        if(m_totalItemsB) {
            QModelIndex index = ui->listView_B->currentIndex();
            int i_testItem = index.row();
            QString fileName = m_listB->at(i_testItem).info;
            if(!fileName.isEmpty())
                textEditLoadText(fileName);
        }
    } else {
        ui->Btn_Test_B->setEnabled(false);
        ui->Btn_Reset_B->setEnabled(false);
        ui->listView_B->setEnabled(false);
    }
}

void MainWindow::on_checkBox_C_stateChanged(int arg1)
{
    if(arg1) {
        ui->Btn_Test_C->setEnabled(true);
        ui->Btn_OK_C->setEnabled(true);
        ui->Btn_NG_C->setEnabled(true);
        ui->Btn_Reset_C->setEnabled(true);
        ui->listView_C->setEnabled(true);

        // load info
        if(m_totalItemsC) {
            QModelIndex index = ui->listView_C->currentIndex();
            int i_testItem = index.row();
            QString fileName = m_listC->at(i_testItem).info;
            if(!fileName.isEmpty())
                textEditLoadText(fileName);
        }
    } else {
        ui->Btn_Test_C->setEnabled(false);
        ui->Btn_OK_C->setEnabled(false);
        ui->Btn_NG_C->setEnabled(false);
        ui->Btn_Reset_C->setEnabled(false);
        ui->listView_C->setEnabled(false);
    }
}

void MainWindow::on_Btn_Test_B_clicked()
{
    if(m_totalItemsB <= 0)
        return;
    QModelIndex index = ui->listView_B->currentIndex();
    setItemStatus(index, E_TEST_PROC, m_modelB, m_proxyModelB);
    int i_testItem = index.row();

    switchTestingType(TT_HALFAUTO);

    ui->textEdit->append("*** " + m_listB->at(i_testItem).name);
    m_thread->setCommand(m_listB->at(i_testItem).command);
    m_thread->start();

    ui->Btn_Test_B->setEnabled(false);
    ui->Btn_Reset_B->setEnabled(false);
}

void MainWindow::on_Btn_Reset_B_clicked()
{
    if(m_totalItemsB <= 0)
        return;
    resetAllItems(ui->listView_B, m_modelB, m_proxyModelB);
}

void MainWindow::on_Btn_Test_C_clicked()
{
//    qDebug() << __FUNCTION__ << __LINE__;
    if(m_totalItemsC <= 0)
        return;
    if(m_thread->isRunning()) {
        return;
    }
//    qDebug() << __FUNCTION__ << __LINE__;
    QModelIndex index = ui->listView_C->currentIndex();
    setItemStatus(index, E_TEST_PROC, m_modelC, m_proxyModelC);
    int i_testItem = index.row();

    switchTestingType(TT_MANUAL);

    ui->textEdit->append("*** " + m_listC->at(i_testItem).name);
//    qDebug() << __FUNCTION__ << __LINE__;
    m_thread->setCmdSync();
    m_thread->setCommand(m_listC->at(i_testItem).command);
    m_thread->start();
//    qDebug() << __FUNCTION__ << __LINE__;

    enableBttons_C(false);
}

void MainWindow::on_Btn_OK_C_clicked()
{
//    qDebug() << __FUNCTION__ << __LINE__;
    if(m_totalItemsC <= 0)
        return;
    QModelIndex index = ui->listView_C->currentIndex();
//    setItemStatus(index, E_TEST_RES_SUCCESS, m_modelC, m_proxyModelC);
    int i_testItem = index.row();

    int next_item;
    QString fileName;

    if(m_thread->isRunning())
    {
//        qDebug() << __FUNCTION__ << __LINE__;
        if(!m_thread2->isRunning())
        {
            if(m_listC->at(i_testItem).exitCmd.isEmpty())
            {
                m_thread2->setCommand("killall " + m_listC->at(i_testItem).command);
            }
            else
            {
                m_thread2->setCommand(m_listC->at(i_testItem).exitCmd);
            }
            m_thread2->start();
        }
        else
        {
            goto out;
        }
    }

    setItemStatus(index, E_TEST_RES_SUCCESS, m_modelC, m_proxyModelC);

    // move to next item
    next_item = i_testItem + 1;
    if(next_item >= m_totalItemsC) {
         next_item = 0;
    }
    index = m_proxyModelC->index(next_item, 0);
    ui->listView_C->setCurrentIndex(index);

    // load info
    fileName = m_listC->at(next_item).info;
    if(!fileName.isEmpty())
        textEditLoadText(fileName);

    switchTestingType(TT_NONE);

out:
//    qDebug() << __FUNCTION__ << __LINE__;
    return;
}

void MainWindow::on_Btn_NG_C_clicked()
{
    if(m_totalItemsC <= 0)
        return;
    QModelIndex index = ui->listView_C->currentIndex();
    int i_testItem = index.row();

    int next_item;
    QString fileName;

    if(m_thread->isRunning())
    {
        if(!m_thread2->isRunning())
        {
            if(m_listC->at(i_testItem).exitCmd.isEmpty())
                m_thread2->setCommand("killall " + m_listC->at(i_testItem).command);
            else
                m_thread2->setCommand(m_listC->at(i_testItem).exitCmd);
        }
        else
        {
            goto out;
        }
        m_thread2->start();
    }

    setItemStatus(index, E_TEST_RES_FAIL, m_modelC, m_proxyModelC);

    // move to next item
    next_item = i_testItem + 1;
    if(next_item >= m_totalItemsC) {
         next_item = 0;
    }
    index = m_proxyModelC->index(next_item, 0);
    ui->listView_C->setCurrentIndex(index);
    fileName = m_listC->at(next_item).info;
    if(!fileName.isEmpty())
        textEditLoadText(fileName);

    switchTestingType(TT_NONE);
out:
    return;
}

void MainWindow::on_Btn_Reset_C_clicked()
{
    if(m_totalItemsC <= 0)
        return;
    if(getTestingType() != TT_NONE)
    {
        if(m_thread->isRunning())
        {
            QModelIndex index = ui->listView_C->currentIndex();
            int i_testItem = index.row();
            if(m_listC->at(i_testItem).exitCmd.isEmpty())
                m_thread2->setCommand("killall " + m_listC->at(i_testItem).command);
            else
                m_thread2->setCommand(m_listC->at(i_testItem).exitCmd);
            m_thread2->start();
        }
        switchTestingType(TT_NONE);
    }
    resetAllItems(ui->listView_C, m_modelC, m_proxyModelC);
    enableBttons_C(true);
}

void MainWindow::on_listView_A_clicked(const QModelIndex &index)
{
    int i_testItem = index.row();
    QString fileName = m_listA->at(i_testItem).info;
    if(!fileName.isEmpty()) {
        textEditLoadText(fileName);
    }
}

void MainWindow::on_listView_B_clicked(const QModelIndex &index)
{
    int i_testItem = index.row();
    QString fileName = m_listB->at(i_testItem).info;
    if(!fileName.isEmpty()) {
        textEditLoadText(fileName);
    }
}

void MainWindow::on_listView_C_clicked(const QModelIndex &index)
{
    int i_testItem = index.row();
    QString fileName = m_listC->at(i_testItem).info;
    if(!fileName.isEmpty()) {
        textEditLoadText(fileName);
    }
}



void MainWindow::on_pushBtn_Entry_clicked()
{
    if(getTestingType() == TT_NONE)
    {
        switchTestingType(TT_PREPARE);
        m_thread->setCommand(m_cmdEnterTestMode);
        m_thread->start();
    }
}

void MainWindow::on_pushBtn_Exit_clicked()
{
    if(getTestingType() == TT_NONE)
    {
        switchTestingType(TT_EXIT);
        m_thread->setCommand(m_cmdExitTestMode);
        m_thread->start();
    }
}

void MainWindow::on_pushBtn_Reload_clicked()
{
    if(getTestingType() != TT_NONE)
        return;

    // read history dir
    QString strDirToOpen;
    QFile file(m_fileHistory);
    bool ret = file.open(QIODevice::ReadOnly | QIODevice::Text);
    if(!ret) {
       qDebug() << "open hsitory failed";
       strDirToOpen = "\\";
    }  else {
        QByteArray byteArray = file.readAll();
        char *str = byteArray.data();
        QString savedFilePath = QString::fromUtf8(str);
        QFileInfo fileInfo(savedFilePath);
        QFileInfo dirInfo(fileInfo.absolutePath());
        if(dirInfo.isDir())
            strDirToOpen = fileInfo.absolutePath();
        else
            strDirToOpen = "\\";
        file.close();
    }

    // choose
    QString fileName = QFileDialog::getOpenFileName(nullptr, 0, strDirToOpen, "*.json");
//    qDebug() << fileName;
    if(fileName.isEmpty())
    {
        return;
    }

    // empty all
    m_modelA->removeRows(0, m_totalItemsA);
    m_modelB->removeRows(0, m_totalItemsB);
    m_modelC->removeRows(0, m_totalItemsC);
    m_listA->clear();
    m_listB->clear();
    m_listC->clear();
    m_totalItemsA = 0;
    m_totalItemsB = 0;
    m_totalItemsC = 0;

    // reload
    ItemParseVal parseRet = getTestItemsFromFile(fileName);
    if(parseRet != E_PARSE_OK)
    {
        //emit(signal_messageBox(1, "文件解析错误"));
        ui->textEdit->append("*** 配置文件解析错误: " + QString::number((int)parseRet));
        return;
    }

    initListView(m_totalItemsA, m_listA, m_modelA, m_proxyModelA, m_delegateA, ui->listView_A);
    initListView(m_totalItemsB, m_listB, m_modelB, m_proxyModelB, m_delegateB, ui->listView_B);
    initListView(m_totalItemsC, m_listC, m_modelC, m_proxyModelC, m_delegateC, ui->listView_C);

    ui->textEdit->append("*** 加载配置文件：成功");
    ui->checkBox_A->setCheckState(Qt::Unchecked);
    ui->checkBox_A->setCheckState(Qt::Checked);

    // save
    file.open(QIODevice::ReadWrite | QIODevice::Text | QFile::Truncate);
    QByteArray byteArr = fileName.toUtf8();
    file.write(byteArr);
    file.close();
}

void MainWindow::on_Btn_Single_A_clicked()
{
    if(m_totalItemsA <= 0)
        return;

    QModelIndex index = ui->listView_A->currentIndex();
    setItemStatus(index, E_TEST_PROC, m_modelA, m_proxyModelA);
    int i_testItem = index.row();

    switchTestingType(TT_AUTO);
    m_bTestSingleA = true;
    ui->textEdit->append("*** " + m_listA->at(i_testItem).name);
    m_thread->setCommand(m_listA->at(i_testItem).command);
    m_thread->start();

    ui->Btn_Test_A->setEnabled(false);
    ui->Btn_Single_A->setEnabled(false);
    ui->Btn_Reset_A->setEnabled(false);
}
